1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 import sun.misc.FpUtils;
32 import sun.misc.DoubleConsts;
33
34 public class Log10Tests {
35 private Log10Tests(){}
36
37 static final double infinityD = Double.POSITIVE_INFINITY;
38 static final double NaNd = Double.NaN;
39 static final double LN_10 = StrictMath.log(10.0);
40
41
42 static java.util.Random rand = new java.util.Random(0L);
43
44 static int testLog10Case(double input, double expected) {
45 int failures=0;
46
47 failures+=Tests.test("Math.log10(double)", input,
48 Math.log10(input), expected);
49
50 failures+=Tests.test("StrictMath.log10(double)", input,
51 StrictMath.log10(input), expected);
52
53 return failures;
54 }
55
56 static int testLog10() {
57 int failures = 0;
58
59 double [][] testCases = {
60 {Double.NaN, NaNd},
61 {Double.longBitsToDouble(0x7FF0000000000001L), NaNd},
62 {Double.longBitsToDouble(0xFFF0000000000001L), NaNd},
63 {Double.longBitsToDouble(0x7FF8555555555555L), NaNd},
64 {Double.longBitsToDouble(0xFFF8555555555555L), NaNd},
65 {Double.longBitsToDouble(0x7FFFFFFFFFFFFFFFL), NaNd},
66 {Double.longBitsToDouble(0xFFFFFFFFFFFFFFFFL), NaNd},
67 {Double.longBitsToDouble(0x7FFDeadBeef00000L), NaNd},
68 {Double.longBitsToDouble(0xFFFDeadBeef00000L), NaNd},
69 {Double.longBitsToDouble(0x7FFCafeBabe00000L), NaNd},
70 {Double.longBitsToDouble(0xFFFCafeBabe00000L), NaNd},
71 {Double.NEGATIVE_INFINITY, NaNd},
72 {-8.0, NaNd},
73 {-1.0, NaNd},
74 {-DoubleConsts.MIN_NORMAL, NaNd},
75 {-Double.MIN_VALUE, NaNd},
76 {-0.0, -infinityD},
77 {+0.0, -infinityD},
78 {+1.0, 0.0},
79 {Double.POSITIVE_INFINITY, infinityD},
80 };
81
82
83 for(int i = 0; i < testCases.length; i++) {
84 failures += testLog10Case(testCases[i][0],
85 testCases[i][1]);
86 }
87
88
89
90
91 double testCase = 1.0;
92 for(int i = 0; i < 23; i++) {
93 failures += testLog10Case(testCase, i);
94 testCase *= 10.0;
95 }
96
97
98
99 for(int i = 0; i < 10000; i++) {
100 double input = Double.longBitsToDouble(rand.nextLong());
101 if(! FpUtils.isFinite(input))
102 continue;
103 else {
104 input = Math.abs(input);
105
106 double expected = StrictMath.log(input)/LN_10;
107 if( ! FpUtils.isFinite(expected))
108 continue;
109 else {
110 double result;
111
112 if( Math.abs(((result=Math.log10(input)) - expected)/Math.ulp(expected)) > 3) {
113 failures++;
114 System.err.println("For input " + input +
115 ", Math.log10 was more than 3 ulps different from " +
116 "log(input)/log(10): log10(input) = " + result +
117 "\tlog(input)/log(10) = " + expected);
118 }
119
120 if( Math.abs(((result=StrictMath.log10(input)) - expected)/Math.ulp(expected)) > 3) {
121 failures++;
122 System.err.println("For input " + input +
123 ", StrictMath.log10 was more than 3 ulps different from " +
124 "log(input)/log(10): log10(input) = " + result +
125 "\tlog(input)/log(10) = " + expected);
126 }
127
128
129 }
130 }
131 }
132
133
134
135
136 {
137 double neighbors[] = new double[40];
138 double neighborsStrict[] = new double[40];
139 double z = Double.NaN;
140
141
142 neighbors[0] = Math.log10(1.0);
143 neighborsStrict[0] = StrictMath.log10(1.0);
144
145 double input[] = new double[40];
146 int half = input.length/2;
147
148
149
150
151 double up = Double.NaN;
152 double down = Double.NaN;
153 for(int i = 0; i < half; i++) {
154 if (i == 0) {
155 input[half] = 1.0;
156 up = FpUtils.nextUp(1.0);
157 down = FpUtils.nextDown(1.0);
158 } else {
159 input[half + i] = up;
160 input[half - i] = down;
161 up = FpUtils.nextUp(up);
162 down = FpUtils.nextDown(down);
163 }
164 }
165 input[0] = FpUtils.nextDown(input[1]);
166
167 for(int i = 0; i < neighbors.length; i++) {
168 neighbors[i] = Math.log10(input[i]);
169 neighborsStrict[i] = StrictMath.log10(input[i]);
170
171
172 z = input[i] - 1.0;
173 double expected = (z - (z*z)*0.5)/LN_10;
174 if ( Math.abs(neighbors[i] - expected ) > 3*Math.ulp(expected) ) {
175 failures++;
176 System.err.println("For input near 1.0 " + input[i] +
177 ", Math.log10(1+z) was more than 3 ulps different from " +
178 "(z-(z^2)/2)/ln(10): log10(input) = " + neighbors[i] +
179 "\texpected about = " + expected);
180 }
181
182 if ( Math.abs(neighborsStrict[i] - expected ) > 3*Math.ulp(expected) ) {
183 failures++;
184 System.err.println("For input near 1.0 " + input[i] +
185 ", StrictMath.log10(1+z) was more than 3 ulps different from " +
186 "(z-(z^2)/2)/ln(10): log10(input) = " + neighborsStrict[i] +
187 "\texpected about = " + expected);
188 }
189
190
191 if( i > 0) {
192 if( neighbors[i-1] > neighbors[i] ) {
193 failures++;
194 System.err.println("Monotonicity failure for Math.log10 at " + input[i] +
195 " and prior value.");
196 }
197
198 if( neighborsStrict[i-1] > neighborsStrict[i] ) {
199 failures++;
200 System.err.println("Monotonicity failure for StrictMath.log10 at " + input[i] +
201 " and prior value.");
202 }
203 }
204 }
205
206 }
207
208 return failures;
209 }
210
211 public static void main(String argv[]) {
212 int failures = 0;
213
214 failures += testLog10();
215
216 if (failures > 0) {
217 System.err.println("Testing log10 incurred "
218 + failures + " failures.");
219 throw new RuntimeException();
220 }
221 }
222
223 }